package net.esj.auth.pojo;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import net.esj.basic.core.view.RequestUtils;
import net.esj.basic.pojo.AbstractPojo;
import net.esj.basic.pojo.TreeStructure;
import net.esj.basic.pojo.op.AuthFunction;
import net.esj.basic.utils.Validators;

import org.apache.commons.lang.StringUtils;

public class CoreAuthFunc extends AbstractPojo<String> implements AuthFunction{

	private String id;
	private String name;
	private Integer sort;
	private String url;
	private String operations;
	private CoreAuthFunc parent;
	private Boolean isMenu;
	private String icon;
	private Integer durable;
	private Set<CoreAuthFunc> children = new HashSet<CoreAuthFunc>();
	private CoreAuthModel model;
	private boolean disabled;
	private int priority;
	
	/**
	 * 自定义函数
	 */
	private String define;
	
	/**
	 * 是否为操作
	 */
	private boolean isOper;
	
	/**
	 * 操作范围
	 */
	private String scope;
	
	private String defineCheck;
	
	private Map<String,Map<String,String[]>> rights = Collections.EMPTY_MAP;
	private Map<String, String[]> params = new HashMap<String, String[]>();
	
	/**
	 * 功能集的分隔符
	 */
	public static final String OPERATION_SPLIT = "@";
	
	public Set<CoreAuthFunc> getChildren() {
		return children;
	}

	public void setChildren(Set<CoreAuthFunc> children) {
		this.children = children;
	}

	@Override
	public String getId() {
		return id;
	}

	@Override
	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getSort() {
		return sort;
	}

	public void setSort(Integer sort) {
		this.sort = sort;
	}

	public String getUrl() {
		return url;
	}
	
	public String getAnalyzedUrl(){
		return analyzeRightUrl(url);
	}

	public void setUrl(String url) {
		this.url = url;
		this.params = analyzeRightParams(url);
	}

	public String getOperations() {
		return operations;
	}

	public void setOperations(String operations) {
		this.operations = operations;
	}

	public CoreAuthFunc getParent() {
		return parent;
	}

	public void setParent(CoreAuthFunc parent) {
		this.parent = parent;
	}

	public Boolean getIsMenu() {
		return isMenu;
	}

	public void setIsMenu(Boolean isMenu) {
		this.isMenu = isMenu;
	}

	public Integer getDurable() {
		return durable;
	}

	public void setDurable(Integer durable) {
		this.durable = durable;
	}

	public CoreAuthModel getModel() {
		return model;
	}

	public void setModel(CoreAuthModel model) {
		this.model = model;
	}

	public boolean isDisabled() {
		return disabled;
	}

	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	public int getPriority() {
		return priority;
	}

	public void setPriority(int priority) {
		this.priority = priority;
	}

	public String getScope() {
		return scope;
	}

	public void setScope(String scope) {
		this.scope = scope;
	}

	@Override
	public Map<String,Map<String,String[]>> getRights(){
		if(rights == Collections.EMPTY_MAP){
			rights = new HashMap<String,Map<String,String[]>>();
			if(!Validators.isEmpty(getOperations())){
				String[] urlArr = StringUtils.split(getOperations(), OPERATION_SPLIT);
				for(String str : urlArr){
					rights.put(analyzeRightUrl(str), analyzeRightParams(str));
				}
			}
		}
		return rights;
	}
	
	
	/**************************for tree ***************************************/
	
	@Override
	public Collection<CoreAuthFunc> getChildNodes() {
		return getChildren();
	}

	@Override
	public String getNodeClsIcon() {
		return icon;
	}

	@Override
	public Integer getNodeLoadType() {
		return TREE_LOAD_TYPE_ON_CLICK_PARENT;
	}

	@Override
	public String getNodeTitle() {
		return getName();
	}

	@Override
	public CoreAuthFunc getParentNode() {
		return getParent();
	}

	@Override
	public Boolean hasCheckBox() {
		return true;
	}

	@Override
	public Boolean hasChildNode() {
		return getChildren()!=null && !getChildren().isEmpty();
	}

	@Override
	public Boolean isNodeExpansion() {
		return true;
	}

	@Override
	public Boolean isSelectCascade() {
		return true;
	}

	public String getIcon() {
		return icon;
	}

	public void setIcon(String icon) {
		this.icon = icon;
	}

	public String getDefine() {
		return define;
	}

	public void setDefine(String define) {
		this.define = define;
	}

	public boolean getIsOper() {
		return isOper;
	}

	public void setIsOper(boolean isOper) {
		this.isOper = isOper;
	}

	public String getDefineCheck() {
		return defineCheck;
	}

	public void setDefineCheck(String defineCheck) {
		this.defineCheck = defineCheck;
	}

	@Override
	public Serializable getNodeId() {
		return this.id;
	}

	public static final String analyzeRightUrl(String rightUrl){
		if(rightUrl.indexOf("?")>0){
			return rightUrl.substring(0, rightUrl.indexOf("?"));
		}else{
			return rightUrl;
		}
	}
	
	public static final Map<String, String[]> analyzeRightParams(String rightUrl){
		if(rightUrl.indexOf("?")>0){
			String parStr = rightUrl.substring(rightUrl.indexOf("?")+1);
			Map<String, String[]> map = RequestUtils.parseQueryString(parStr);
			return map;
		}else{
			return Collections.EMPTY_MAP;
		}
	}
	
	public static final boolean checkParams(Map<String, String[]> params,Map requestParams){
		boolean pass = true;
		for(Object o :params.entrySet()){
			Map.Entry<String, String[]> entry = (Entry) o;
			Object v = requestParams.get(entry.getKey());
			if(v!=null && v.getClass().isArray()){
				v = ((Object[])v)[0];
			}
			if(v== null){
				return false;
			}
			boolean has = false;
			for(String str : entry.getValue()){
				if(v.equals(str)){
					has |= true;
				}
			}
			pass &= has;
		}
		return pass;
	}

	public Map<String, String[]> getParams() {
		return params;
	}
	
}
